package com.sinog.biz.interceptor;

import com.sinog.biz.config.ProvinceCodesConfig;
import com.sinog.biz.util.SqlPaserUtil;
import com.sinog.biz.util.SqlUtil;
import com.sinog.biz.util.smlib.Sm4;
import com.sinog.core.domain.AbLieguan;
import com.sinog.core.domain.PrisonerMain;
import com.sinog.core.domain.PrisonerSr;
import com.sinog.core.domain.PrisonerZn;
import com.sinog.core.domain.StaffInfoManage;
import com.sinog.core.domain.VolunteerManageInfo;
import com.sinog.core.util.GkObjectUtils;
import com.sinog.core.util.IdNumUtil;
import com.sinog.core.util.PhoneUtil;
import com.sinog.core.utilbean.Constants;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @desc 拦截系统中所有的更新SQL（使用时将头部的注释去掉）
 * 省级数据同步功能说明：
 *  1. 当系统所部署的省份与罪犯服刑单位所在省份或者户籍地所在省份不一致的时候，就需要将数据发送到不一致的省份。
 *  2. 思路：
 *  1) 先根据SQL语句获取到(prinum,pid,id,singleid,pp等字段)
 *  2) 如果通过SQL语句获取到的字段是pid,id,singleid,pp等字段，需要通过字段值以及表名获取到罪犯编号。如果表中不存在罪犯编号字段，则不调用省级接口。
 *  3) 通过不一致的省份code,获取对应的省份的接口url，然后将数据发送给所对应的的省份。
 *  3. 存在的问题：
 *  1) 户籍的迁入迁出功能没有实现。
 *  2) 当增加一个业务表的时候，	需要修改determinePrinum()方法
 * @author dangyf
 * @date 2020年04月01日 11点12分
 */
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class,Object.class}),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class})})
@org.springframework.context.annotation.Configuration
@ConditionalOnProperty(name = "gkzx.azbj.dataSync.open", havingValue = "true")
public class SqlInterceptor implements Interceptor {

    private static final Logger log = LoggerFactory.getLogger(SqlInterceptor.class);
    private static final SyncInterface SYNC_INTERFACE;
    private static final ThreadPoolTaskExecutor EXECUTOR = new ThreadPoolTaskExecutor();
    private static final Map<String,String> URL_MAP = new HashMap<>(64);

    static {
        SYNC_INTERFACE = new SyncData();
        EXECUTOR.initialize();
        //核心线程数
        EXECUTOR.setCorePoolSize(50);
        //最大线程数
        EXECUTOR.setMaxPoolSize(100);
        //缓冲队列
        EXECUTOR.setQueueCapacity(500);
        //允许线程的空闲时间
        EXECUTOR.setKeepAliveSeconds(1);
        //线程前缀
        EXECUTOR.setThreadNamePrefix("taskAsync001-");
        //线程策略
        EXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        EXECUTOR.setWaitForTasksToCompleteOnShutdown(true);
        EXECUTOR.setAwaitTerminationSeconds(60);
    }

    /**
     * 拦截器
     * @param invocation invocation
     * @return Object
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //0、读取application-*.yml配置文件中属性
        ProvinceCodesConfig provinceCodesConfig = CodesHelper.getInstance();
        List<Map<String,String>> valueMapList = provinceCodesConfig.getValueMapList();
        for(Map<String,String> m : valueMapList) {
            URL_MAP.putAll(m);
        }
        String localCode = URL_MAP.get("local-code");
        String dataSyncFashion = URL_MAP.get("data-sync-fashion");
        String ifOpenIdnumTm = URL_MAP.get("IF_OPEN_IDNUM_TM");
        List<String> excludeTable = new ArrayList<>(Arrays.asList(URL_MAP.get("exclude-tables").split(",")));
        log.debug("\n>>>>>>>>>>>>>>>拦截sql开始<<<<<<<<<<<<<<<");
        //1、定义方法返回结果
        Object result;
        long start = System.currentTimeMillis();
        //2、取出sql，并进行处理
        MappedStatement mappedStatement = (MappedStatement)invocation.getArgs()[0];
        Object parameterObject = null;
        if(1 < invocation.getArgs().length) {
            parameterObject = invocation.getArgs()[1];
        }
        String statementId = mappedStatement.getId();
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        String sqlt = boundSql.getSql().toLowerCase();
        //3、组装sql字符串
        //获取参数
        Configuration configuration = mappedStatement.getConfiguration();
        DataSource dataSource = configuration.getEnvironment().getDataSource();
        String name = mappedStatement.getSqlCommandType().name();
        String sql = "";
        JdbcTemplate template = null;
        // 罪犯编号
        String prino = "";
        // 是否调用省级接口的标志位
        boolean flag = false;
        if(!"select".equalsIgnoreCase(name)) {
            template = new JdbcTemplate(dataSource);
            //将SQL中带?的替换为实际参数
            sql = SqlUtil.getSql(boundSql,parameterObject,configuration);
            log.debug("\n[执行语句ID:{}] - \n[sql类型:{}] - \n[拼接参数后的sql:{}]",statementId,name,sql);
            //4、先检查是否需要调用其他省，在执行本省sql之后执行删除的场景会查不到数据
            // 用于获取id primun singleid pp
            Map<String,String> idOrPriNum = SqlUtil.getIdOrPriNum(boundSql,parameterObject,configuration);
            log.debug("\n根据SQL语句获取罪犯编号...");
            // 用于获取罪犯编号
            Map<String,String> funMap = SqlUtil.determinePrinum(idOrPriNum,template,sqlt);
            if("true".equals(funMap.get("flag"))) {
                flag = true;
                prino = funMap.get("prinum");
                //如果是prisoner_main、prisoner_zn、prisoner_sr、prisoner_zz、prisoner_fx、prisave_temp、prisoner_hc表
                //判断目前该数据对应的犯罪编号是否已经是发起核查
                boolean f = sqlt.contains("prisoner_main") || sqlt.contains("prisoner_zn") || sqlt
                        .contains("prisoner_sr") || sqlt.contains("prisoner_zz") || sqlt.contains("prisoner_fx") || sqlt
                        .contains("prisave_temp") || sqlt.contains("prisoner_hc");
                //如果是同步上面表，并且是http方式，则不通过该方式同步。
                if(f && StringUtils.equals(dataSyncFashion,"http")) {
                    String temSql = "select state from prisoner_main where pri_num = '" + prino + "'";
                    String state = "";
                    try {
                        state = template.queryForObject(temSql,String.class);
                    } catch(DataAccessException e) {
                        log.error(e.getMessage());
                    }
                    if((Constants.NumberStr.NUM_STR_ZERO.equals(state) || Constants.NumberStr.NUM_STR_ONE.equals(state) || "".equals(state))) {
                        flag = false;
                    }
                }
            }
            log.debug("\n[获取到的犯罪编号为:{}] - \n[是否需要同步数据到其他省份:{}]",prino,flag ? "是" : "否");
            log.debug("\n>>>>>>>>>>>>>>>>>>>>开始执行本地sql......<<<<<<<<<<<<<<<<<<<<");
        }
        //5、执行本省SQL语句
        result = invocation.proceed();
        //身份证解密
        if("com.sinog.biz.mapper.havexml.PrisonerMainMapper.getInmatesList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getReleaseHelpEduList2"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getReleaseHelpEduList1"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerZnMapper.getNoAdultList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getVerificationList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getXxblList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getSsjList"
                // 下面注釋掉的是找不到mapper或者找不到mapper中的方法 先不刪
                //.equals(statementId) || "com.sinog.biz.mapper.havexml.AbMvMapper.getShgxChildrenList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getQbryglList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbTuoguanMapper.getTuoguanlList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getUnSettleList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.StaffInfoManageMapper.selectStaffInfoForExport"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getDownSettleList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getJdInfoList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getReleaseHelpEduList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getWxjList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.DadcMapper.hcxxh"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.DadcMapper.hchzd"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.DadcMapper.xjh"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.DadcMapper.xjhzd"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.DadcMapper.bjgzfa"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AdvanSearchMapper.selectSqltext"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.XtjcKsywxtMapper.getWorkCoordinationList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getArchivesManagerList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainExcelTempMapper.getInmatesList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getBlInmatesList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getZfBaseInfoList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getUnZfBaseInfoList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.WorkMapper.getWorks"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.PrisonerTransferMapper.getFqTranslateBaseInfoList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getSlgJzd"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getSlgHjd"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.nameRepetitionInfo"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getMoveSettleList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbMvMapper.getHjqcglList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbMvMapper.getHjqrglList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbMvMapper.getMvBaseInfoForCheck"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerSrMapper.getSrInfo"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerSrMapper.getShgxParentList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerZnMapper.getNoAdultList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.OrgStaffInfoMapper.getOrgStaffInfoList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.SocialTrainingMapper.getSocialTrainingList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.GovernmentHelpMapper.getxxblList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getQbryList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbAnzhiMapper.getMoveSettleList"
                .equals(statementId)
                ){
            if("select".equalsIgnoreCase(name)) {
                if(result instanceof ArrayList) {
                    ArrayList resultList = (ArrayList)result;
                    // 执行sql解析并获取所有执行列名称
                    Map<String, String> resultMap = SqlPaserUtil.getColumnForSql(boundSql.getSql(),statementId);
                    for(Object o : resultList) {
                        boolean f = null != o &&  StringUtils.startsWithAny(o.toString(),"PrisonerMain","PrisonerZn","PrisonerSr");
                        if(f) {
                            if(o.toString().startsWith("PrisonerMain")) {
                                PrisonerMain mm = (PrisonerMain)o;
                                if(ObjectUtils.allNotNull(mm.getIdNum()) && !"".equals(mm.getIdNum())) {
                                    if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                        mm.setIdNum(IdNumUtil.deSensitiZation(Sm4.decryptEcb(mm.getIdNum())));
                                    } else {
                                        mm.setIdNum(Sm4.decryptEcb(mm.getIdNum()));
                                    }
                                }
                            } else if(o.toString().startsWith("PrisonerZn")) {
                                PrisonerZn mm = (PrisonerZn)o;
                                if(ObjectUtils.allNotNull(mm.getZnsfId()) && !"".equals(mm.getZnsfId())) {
                                    if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                        mm.setZnsfId(IdNumUtil.deSensitiZation(Sm4.decryptEcb(mm.getZnsfId())));
                                    } else {
                                        mm.setZnsfId(Sm4.decryptEcb(mm.getZnsfId()));
                                    }
                                }
                            } else if(o.toString().startsWith("PrisonerSr")) {
                                PrisonerSr mm = (PrisonerSr)o;
                                if(ObjectUtils.allNotNull(mm.getIdnumber()) && !"".equals(mm.getIdnumber())) {
                                    if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                        mm.setIdnumber(IdNumUtil.deSensitiZation(Sm4.decryptEcb(mm.getIdnumber())));
                                    } else {
                                        mm.setIdnumber(Sm4.decryptEcb(mm.getIdnumber()));
                                    }
                                }
                            }
                            // 设置默认属性值
                            GkObjectUtils.putDefaultProperties(o);
                        } else if(o instanceof HashMap) {
                            Map m = (Map)o;
                            if(null != m.get("idnum") && !"".equals(m.get("idnum"))) {
                                if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                    //用于工作台导出明文身份证
                                    m.put("idnumOpen",Sm4.decryptEcb(m.get("idnum").toString()));
                                    m.put("idnum",IdNumUtil.deSensitiZation(Sm4.decryptEcb(m.get("idnum").toString())));
                                } else {
                                    m.put("idnum",Sm4.decryptEcb(m.get("idnum").toString()));
                                }
                            }
                            if(null != m.get("idNum") && !"".equals(m.get("idNum"))) {
                                if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                    m.put("idnumOpen",Sm4.decryptEcb(m.get("idNum").toString()));
                                    m.put("idNum",IdNumUtil.deSensitiZation(Sm4.decryptEcb(m.get("idNum").toString())));
                                } else {
                                    m.put("idNum",Sm4.decryptEcb(m.get("idNum").toString()));
                                }
                            }
                            if(null != m.get("znsfid") && !"".equals(m.get("znsfid"))) {
                                if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                    m.put("znsfid",IdNumUtil.deSensitiZation(Sm4.decryptEcb(m.get("znsfid")
                                                                                             .toString())));
                                } else {
                                    m.put("znsfid",Sm4.decryptEcb(m.get("znsfid").toString()));
                                }
                            }
                            if(null != m.get("sfzh") && !"".equals(m.get("sfzh"))) {
                                if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                    m.put("sfzh",IdNumUtil.deSensitiZation(Sm4.decryptEcb(m.get("sfzh").toString())));
                                } else {
                                    m.put("sfzh",Sm4.decryptEcb(m.get("sfzh").toString()));
                                }
                            }
                            if(null != m.get("idNumber") && !"".equals(m.get("idNumber"))) {
                                if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                    m.put("idNumber",IdNumUtil.deSensitiZation(Sm4.decryptEcb(m.get("idNumber")
                                                                                               .toString())));
                                } else {
                                    m.put("idNumber",Sm4.decryptEcb(m.get("idNumber").toString()));
                                }
                            }
                            // 设置默认属性值
                            putDefaultValue(resultMap,m,statementId);
                        }
                    }
                }
                return result;
            }
        } else if ("com.sinog.biz.mapper.havexml.PrisonerMainMapper.selectById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerZnMapper.selectById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.VerificationMapper.getPrisonerHcById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getBaseInfoViewByPriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getHcjlInfoViewByPriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbMvMapper.getBaseInfoViewByPriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.PrisonerTransferMapper.getBaseInfoByPriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbTuoguanMapper.getTuoguanJlInfoById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbTuoguanMapper.getTuoguanInfoById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbAnzhiMapper.getBaseInfoBypriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerSrMapper.selectById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.selectPrisonerMain"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerTransferMapper.getBaseInfoByPriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.PrisonerMainMapper.getBaseInfoViewByPriNumLg"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getPrisonerBaseInfo"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.other.PrisonerTransferMapper.getPrisonerList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getPrisonerListByKey"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getPrisonerList"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getBaseInfoByPriNum"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbMvMapper.getBaseInfoByPriNum"
                //安置/待安置
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getBaseInfoBypriNum"
                //失联人员中找回页面
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getTuoguanInfoById"
                //失联记录页面
                .equals(statementId) || "com.sinog.biz.mapper.havexml.AbPrisonerMapper.getTuoguanJlInfoById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.VolunteerManageMapper.selectById"
                .equals(statementId) || "com.sinog.biz.mapper.havexml.StaffInfoManageMapper.selectById"
                .equals(statementId)
        ) {
            if ("select".equalsIgnoreCase(name)) {
                // 执行sql解析并获取所有执行列名称
                if (result instanceof ArrayList) {
                    ArrayList resultList = (ArrayList) result;
                    for(Object o : resultList) {
                        boolean f = null != o &&  StringUtils.startsWithAny(o.toString(),"PrisonerMain","PrisonerZn","PrisonerSr","VolunteerManageInfo","StaffInfoManage");
                        if(f) {
                            if(o.toString().startsWith("PrisonerMain")) {
                                PrisonerMain mm = (PrisonerMain)o;
                                if(ObjectUtils.allNotNull(mm.getIdNum()) && !"".equals(mm.getIdNum())) {
                                    mm.setIdNum(Sm4.decryptEcb(mm.getIdNum()));
                                }
                            } else if(o.toString().startsWith("PrisonerZn")) {
                                PrisonerZn mm = (PrisonerZn)o;
                                if(ObjectUtils.allNotNull(mm.getZnsfId()) && !"".equals(mm.getZnsfId())) {
                                    mm.setZnsfId(Sm4.decryptEcb(mm.getZnsfId()));
                                }
                            } else if(o.toString().startsWith("PrisonerSr")) {
                                PrisonerSr mm = (PrisonerSr)o;
                                if(ObjectUtils.allNotNull(mm.getIdnumber()) && !"".equals(mm.getIdnumber())) {
                                    mm.setIdnumber(Sm4.decryptEcb(mm.getIdnumber()));
                                }
                            } else if(o.toString().startsWith("VolunteerManageInfo")) {
                                VolunteerManageInfo mm = (VolunteerManageInfo)o;
                                if(ObjectUtils.allNotNull(mm.getSfzh()) && !"".equals(mm.getSfzh())) {
                                    mm.setSfzh(Sm4.decryptEcb(mm.getSfzh()));
                                }
                            } else if(o.toString().startsWith("StaffInfoManage")) {
                                StaffInfoManage mm = (StaffInfoManage)o;
                                if(ObjectUtils.allNotNull(mm.getSfzh()) && !"".equals(mm.getSfzh())) {
                                    mm.setSfzh(Sm4.decryptEcb(mm.getSfzh()));
                                }
                            }
                        } else if(o instanceof HashMap) {
                            Map m = (Map)o;
                            if(m.get("idnum") != null && !"".equals(m.get("idnum"))) {
                                m.put("idnum",Sm4.decryptEcb(m.get("idnum").toString()));
                            }
                            if(m.get("idNum") != null && !"".equals(m.get("idNum"))) {
                                if(StringUtils.equals(Constants.NumberStr.NUM_STR_ONE,ifOpenIdnumTm)) {
                                    m.put("idNum",Sm4.decryptEcb(m.get("idNum").toString()));
                                } else {
                                    m.put("idNum",Sm4.decryptEcb(m.get("idNum").toString()));
                                }
                            }
                            if(m.get("znsfid") != null && !"".equals(m.get("znsfid"))) {
                                m.put("znsfid",Sm4.decryptEcb(m.get("znsfid").toString()));
                            }
                            if(m.get("sfzh") != null && !"".equals(m.get("sfzh"))) {
                                m.put("sfzh",Sm4.decryptEcb(m.get("sfzh").toString()));
                            }
                            if(m.get("idNumber") != null && !"".equals(m.get("idNumber"))) {
                                m.put("idNumber",Sm4.decryptEcb(m.get("idNumber").toString()));
                            }
                        }
                    }
                }
                return result;
            }
        }
        if ("select".equalsIgnoreCase(name)) {
            return result;
        }
        long timing = System.currentTimeMillis() - start;
        log.debug("\n>>>>>>>>>>>>>>>>>>>>执行本省系统sql完毕......<<<<<<<<<<<<<<<<<<<< - [耗时:{} ms]",timing);
        //6、去除不需要同步的的表
        log.debug("\n开始过滤无需同步的表...");
        //定义是否执行跨省部数据同步，true：同步，false：不同步
        AtomicBoolean tableFlag = new AtomicBoolean(true);
        excludeTable.forEach(table -> {
            if(sqlt.contains(table)) {
                tableFlag.set(false);
            }
        });
        if(statementId.startsWith("com.sinog.biz.mapper.havexml.other.SwitchToOriginalInvestigationOrganMapper")) {
            tableFlag.set(false);
        }
        //排除 通知公告同步
        if(statementId.startsWith("com.sinog.biz.mapper.havexml.NoticeInfoManageMapper")) {
            tableFlag.set(false);
        }
        //排除 帮教资料同步
        if(statementId.startsWith("com.sinog.biz.mapper.havexml.AzbjDatabaseInfoMapper")) {
            tableFlag.set(false);
        }
        //排除 政策文件同步
        if(statementId.startsWith("com.sinog.biz.mapper.havexml.ZcwjMapper")) {
            tableFlag.set(false);
        }
        //排除 经验推介同步
        if(statementId.startsWith("com.sinog.biz.mapper.havexml.JytjMapper")) {
            tableFlag.set(false);
        }
        //排除 运维功能-自动生成测试账号
        if(statementId.startsWith("com.sinog.biz.mapper.havexml.other.GenerateAccountMapper")) {
            tableFlag.set(false);
        }
        log.debug("\n过滤结束...，该sql是否需要同步:{}",tableFlag.get() ? "需要" : "不需要");
        //7、向跨省/部同步数据
        if(tableFlag.get() && !"select".equalsIgnoreCase(name)) {
            //8、同步到部级
            String finalSqlB = sql;
            JdbcTemplate finalTemplate = template;
            // 用于获取id primun singleid pp
            Map<String,String> idOrPriNum = SqlUtil.getIdOrPriNum(boundSql,parameterObject,configuration);
            log.debug("\n根据SQL语句获取罪犯编号...");
            // 用于获取罪犯编号
            Map<String,String> funMap = SqlUtil.determinePrinum(idOrPriNum,template,sqlt);
            EXECUTOR.submit(() -> {
                //增删改
                if(StringUtils.equals(dataSyncFashion,"middle")) {
                    // "Z"特殊字符 区分自建省份和部署省份
                    if(StringUtils.contains(funMap.get("prinum"),"Z")) {
                        if("update".equalsIgnoreCase(name) || sqlt.contains("ab_prisoners")) {
                            SYNC_INTERFACE.syncZjSqlBySql(finalSqlB,finalTemplate,funMap.get("prinum"));
                        }
                    } else {
                        SYNC_INTERFACE.syncBuSqlBySql(finalSqlB,finalTemplate);
                    }
                } else {
                    log.error(">>>>>系统数据同步方式配置错误,可选值['http','middle']<<<<<");
                }
                return "ok";
            });
            //9、同步到省级
            if(flag) {
                String temSql = "select nativepro from prisoner_main where pri_num = '" + prino + "'";
                // 户籍地址所在省code
                String nativepro = "";
                try {
                    nativepro = template.queryForObject(temSql,String.class);
                } catch(DataAccessException e) {
                    log.error("查询结果和预期不一致");
                }
                String priNativepro = prino.substring(0,2) + "0000";
                // 本省code是否和户籍地是否相等，如果相等就取服刑所在省，如果不相等就取户籍地
                String code = localCode.equals(nativepro) ? priNativepro : nativepro;
                boolean slgFlag = false;
                if(sql.contains("INSERT INTO ab_lieguan")) {
                    if(parameterObject instanceof AbLieguan) {
                        assert code != null;
                        if(!((AbLieguan)parameterObject).getVillid().substring(0,2).equals(code.substring(0,2))) {
                            slgFlag = true;
                        }
                    }
                }
                //如果该犯罪编号对应人员已经双列管则不需要再进行同步数据
                String findLieGuanStateSql = "select shen_state from ab_lieguan where pri_num = '" + prino + "'";
                //是否已经双列管
                boolean isSlgFlag = false;
                try {
                    String shenState = template.queryForObject(findLieGuanStateSql,String.class);
                    if(Constants.NumberStr.NUM_STR_ONE.equals(shenState)) {
                        isSlgFlag = true;
                    }
                } catch (EmptyResultDataAccessException e) {
                    log.error("查询结果为空");
                } catch(DataAccessException e) {
                    log.error("查询结果和预期不一致");
                }
                if(localCode.equals(code) && !slgFlag) {
                    if(log.isDebugEnabled()) {
                        log.debug("\n该服刑人员所在的户籍地与原侦查机关所在省一致，无需同步");
                    }
                    return result;
                } else {
                    if(isSlgFlag) {
                        return result;
                    }
                    String finalSqlS = sql;
                    String finalNativepro = nativepro;
                    String finalPrino = prino;
                    EXECUTOR.submit(new Callable<String>() {
                        @Override
                        public String call() throws Exception {
                            if (StringUtils.equals(dataSyncFashion, "middle")) {
                                SYNC_INTERFACE.syncSjSqlBySql(finalSqlS, name, finalNativepro, finalPrino, finalTemplate);
                            } else {
                                log.error(">>>>>系统数据同步方式配置错误,可选值['http','middle']<<<<<");
                            }
                            return "ok";
                        }
                    });
                }
            }
        }
        return result;
    }

    /**
     * 描述
     * @param arg0 arg0
     * @return Object
     */
    @Override
    public Object plugin(Object arg0) {
        return Plugin.wrap(arg0,new SqlInterceptor());
    }

    /**
     * 描述
     * @param properties properties
     */
    @Override
    public void setProperties(Properties properties) {
    }

    /**
     * 为属性赋予默认值
     * @param resultMap resultMap
     * @param paramMap paramMap
     * @param statementId statementId
     */
    public static void putDefaultValue(Map<String,String> resultMap,Map<String,String> paramMap,String statementId) {
        //身份证解密
        if("com.sinog.biz.mapper.havexml.PrisonerMainMapper.getInmatesList".equals(statementId)
                || "com.sinog.biz.mapper.havexml.PrisonerMainExcelTempMapper.getInmatesList".equals(statementId)
                || "com.sinog.biz.mapper.havexml.PrisonerSrMapper.getSrInfo".equals(statementId)
                || "com.sinog.biz.mapper.havexml.PrisonerZnMapper.getNoAdultList".equals(statementId)
                || "com.sinog.biz.mapper.havexml.PrisonerSrMapper.getShgxParentList".equals(statementId)
                || "com.sinog.biz.mapper.havexml.SocialTrainingMapper.getSocialTrainingList".equals(statementId)
                || "com.sinog.biz.mapper.havexml.GovernmentHelpMapper.getxxblList".equals(statementId)
        ){
            for (Map.Entry<String, String> entry : resultMap.entrySet()) {
                String key = entry.getKey();
                try {
                    if(!paramMap.containsKey(key)) {
                        paramMap.put(entry.getKey(),entry.getValue());
                    } else if(paramMap.containsKey(key) && StringUtils.isBlank(paramMap.get(key))) {
                        paramMap.put(entry.getKey(),entry.getValue());
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
            if(paramMap.containsKey(Constants.PhoneAndTel.TEL)) {
                Map<String,String> dianhua;
                String tel = paramMap.get(Constants.PhoneAndTel.TEL);
                String phone1 = paramMap.get(Constants.PhoneAndTel.PHONE);
                if(StringUtils.isBlank(phone1)) {
                    dianhua = PhoneUtil.splitTelAndPhone(tel);
                } else {
                    dianhua = PhoneUtil.splitTelAndPhone(phone1);
                }
                paramMap.put(Constants.PhoneAndTel.TEL, StringUtils.isBlank(dianhua.get(Constants.PhoneAndTel.TEL)) ? Constants.StrFinalValue.WU:dianhua.get(Constants.PhoneAndTel.TEL));
                paramMap.put(Constants.PhoneAndTel.PHONE,StringUtils.isBlank(dianhua.get(Constants.PhoneAndTel.PHONE)) ? Constants.StrFinalValue.WU:dianhua.get(Constants.PhoneAndTel.PHONE));
            }
        }
    }
}